# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
#   📄 PANDOC-SERVER - Makefile
#   MCP server for pandoc document conversion
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
#
# Author : Mihai Criveti
# Usage  : make <target>   or just `make help`
#
# help: 📄 PANDOC-SERVER (Go MCP server for document conversion)
# ─────────────────────────────────────────────────────────────────────────

# =============================================================================
# 📖 DYNAMIC HELP
# =============================================================================
.PHONY: help
help:
	@grep '^# help\:' $(firstword $(MAKEFILE_LIST)) | sed 's/^# help\: //'

# =============================================================================
# 📦 PROJECT METADATA
# =============================================================================
MODULE          := pandoc-server
BIN_NAME        := pandoc-server
VERSION         ?= $(shell git describe --tags --dirty --always 2>/dev/null || echo "v0.2.0")

DIST_DIR        := dist
COVERPROFILE    := $(DIST_DIR)/coverage.out
COVERHTML       := $(DIST_DIR)/coverage.html

GO              ?= go
GOOS            ?= $(shell $(GO) env GOOS)
GOARCH          ?= $(shell $(GO) env GOARCH)

LDFLAGS         := -s -w -X 'main.appVersion=$(VERSION)'

ifeq ($(shell test -t 1 && echo tty),tty)
C_GREEN := \033[38;5;82m
C_BLUE  := \033[38;5;75m
C_RESET := \033[0m
else
C_GREEN :=
C_BLUE  :=
C_RESET :=
endif

# =============================================================================
# 🔧 TOOLING
# =============================================================================
# help: 🔧 TOOLING
# help: tools                 - Install golangci-lint & staticcheck

GOBIN := $(shell $(GO) env GOPATH)/bin

.PHONY: tools
tools: $(GOBIN)/golangci-lint $(GOBIN)/staticcheck

$(GOBIN)/golangci-lint:
	@echo "$(C_BLUE)Installing golangci-lint...$(C_RESET)"
	@$(GO) install github.com/golangci/golangci-lint/cmd/golangci-lint@latest

$(GOBIN)/staticcheck:
	@echo "$(C_BLUE)Installing staticcheck...$(C_RESET)"
	@$(GO) install honnef.co/go/tools/cmd/staticcheck@latest

# =============================================================================
# 📂 MODULE & FORMAT
# =============================================================================
# help: 📂 MODULE & FORMAT
# help: tidy                  - go mod tidy + verify
# help: fmt                   - Run gofmt & goimports

.PHONY: tidy fmt

tidy:
	@echo "$(C_BLUE)Tidying dependencies...$(C_RESET)"
	@$(GO) mod tidy
	@$(GO) mod verify

fmt:
	@echo "$(C_BLUE)Formatting code...$(C_RESET)"
	@$(GO) fmt ./...
	@go run golang.org/x/tools/cmd/goimports@latest -w .

# =============================================================================
# 🔍 LINTING & STATIC ANALYSIS
# =============================================================================
# help: 🔍 LINTING & STATIC ANALYSIS
# help: vet                   - go vet
# help: staticcheck           - Run staticcheck
# help: lint                  - Run golangci-lint
# help: pre-commit            - Run all pre-commit hooks

.PHONY: vet staticcheck lint pre-commit

vet:
	@echo "$(C_BLUE)Running go vet...$(C_RESET)"
	@$(GO) vet ./...

staticcheck: tools
	@echo "$(C_BLUE)Running staticcheck...$(C_RESET)"
	@staticcheck ./...

lint: tools
	@echo "$(C_BLUE)Running golangci-lint...$(C_RESET)"
	@golangci-lint run

pre-commit:
	@command -v pre-commit >/dev/null 2>&1 || { \
	    echo '✖ pre-commit not installed → pip install --user pre-commit'; exit 1; }
	@pre-commit run --all-files --show-diff-on-failure

# =============================================================================
# 🧪 TESTS & COVERAGE
# =============================================================================
# help: 🧪 TESTS & COVERAGE
# help: test                  - Run unit tests (race)
# help: test-verbose          - Run tests with verbose output
# help: coverage              - Generate HTML coverage report
# help: test-integration      - Run integration tests

.PHONY: test test-verbose coverage test-integration

test:
	@echo "$(C_BLUE)Running tests...$(C_RESET)"
	@$(GO) test -race -timeout=90s ./...

test-verbose:
	@echo "$(C_BLUE)Running tests (verbose)...$(C_RESET)"
	@$(GO) test -v -race -timeout=90s ./...

coverage:
	@mkdir -p $(DIST_DIR)
	@echo "$(C_BLUE)Generating coverage report...$(C_RESET)"
	@$(GO) test ./... -covermode=count -coverprofile=$(COVERPROFILE)
	@$(GO) tool cover -html=$(COVERPROFILE) -o $(COVERHTML)
	@echo "$(C_GREEN)✔ HTML coverage → $(COVERHTML)$(C_RESET)"

test-integration: build
	@echo "$(C_BLUE)Running integration tests...$(C_RESET)"
	@./test_integration.sh

# =============================================================================
# 🛠 BUILD & RUN
# =============================================================================
# help: 🛠 BUILD & RUN
# help: build                 - Build binary into ./dist
# help: install               - go install into GOPATH/bin
# help: release               - Cross-compile (honours GOOS/GOARCH)
# help: run                   - Build then run (stdio transport)
# help: run-translate         - Run with MCP Gateway translate on :9000

.PHONY: build install release run run-translate

build: tidy
	@mkdir -p $(DIST_DIR)
	@echo "$(C_BLUE)Building $(BIN_NAME)...$(C_RESET)"
	@CGO_ENABLED=0 $(GO) build -trimpath -ldflags '$(LDFLAGS)' -o $(DIST_DIR)/$(BIN_NAME) .
	@echo "$(C_GREEN)✔ Built → $(DIST_DIR)/$(BIN_NAME)$(C_RESET)"

install:
	@echo "$(C_BLUE)Installing $(BIN_NAME)...$(C_RESET)"
	@$(GO) install -trimpath -ldflags '$(LDFLAGS)' .
	@echo "$(C_GREEN)✔ Installed → $(GOBIN)/$(BIN_NAME)$(C_RESET)"

release:
	@mkdir -p $(DIST_DIR)/$(GOOS)-$(GOARCH)
	@echo "$(C_BLUE)Building release for $(GOOS)/$(GOARCH)...$(C_RESET)"
	@GOOS=$(GOOS) GOARCH=$(GOARCH) CGO_ENABLED=0 \
	  $(GO) build -trimpath -ldflags '$(LDFLAGS)' \
	  -o $(DIST_DIR)/$(GOOS)-$(GOARCH)/$(BIN_NAME) .
	@echo "$(C_GREEN)✔ Release → $(DIST_DIR)/$(GOOS)-$(GOARCH)/$(BIN_NAME)$(C_RESET)"

run: build
	@echo "$(C_BLUE)Starting $(BIN_NAME) (stdio)...$(C_RESET)"
	@$(DIST_DIR)/$(BIN_NAME)

run-translate: build
	@echo "$(C_BLUE)Starting $(BIN_NAME) with MCP Gateway on :9000...$(C_RESET)"
	@python3 -m mcpgateway.translate --stdio "$(DIST_DIR)/$(BIN_NAME)" --port 9000

# =============================================================================
# 🐳 DOCKER
# =============================================================================
# help: 🐳 DOCKER
# help: docker-build          - Build container image
# help: docker-run            - Run container (stdio)
# help: docker-test           - Test container with pandoc conversion

IMAGE ?= $(BIN_NAME):$(VERSION)

.PHONY: docker-build docker-run docker-test

docker-build:
	@echo "$(C_BLUE)Building Docker image $(IMAGE)...$(C_RESET)"
	@docker build --build-arg VERSION=$(VERSION) -t $(IMAGE) .
	@docker images $(IMAGE)
	@echo "$(C_GREEN)✔ Docker image → $(IMAGE)$(C_RESET)"

docker-run: docker-build
	@echo "$(C_BLUE)Running Docker container...$(C_RESET)"
	@docker run --rm -i $(IMAGE)

docker-test: docker-build
	@echo "$(C_BLUE)Testing Docker container...$(C_RESET)"
	@echo '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":1}' | \
	  docker run --rm -i $(IMAGE) | python3 -m json.tool

# =============================================================================
# 📚 PANDOC SPECIFIC TESTS
# =============================================================================
# help: 📚 PANDOC TESTS
# help: test-pandoc           - Test pandoc conversion
# help: test-formats          - Test listing formats
# help: test-health           - Test health check

.PHONY: test-pandoc test-formats test-health

test-pandoc: build
	@echo "$(C_BLUE)Testing pandoc conversion...$(C_RESET)"
	@echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"pandoc","arguments":{"from":"markdown","to":"html","input":"# Hello\\n\\nThis is **bold** text."}},"id":1}' | \
	  timeout 2 $(DIST_DIR)/$(BIN_NAME) 2>/dev/null | python3 -m json.tool | head -20

test-formats: build
	@echo "$(C_BLUE)Testing format listing...$(C_RESET)"
	@echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"list-formats","arguments":{"type":"input"}},"id":1}' | \
	  timeout 2 $(DIST_DIR)/$(BIN_NAME) 2>/dev/null | python3 -c "import json, sys; d=json.loads(sys.stdin.read()); print('Input formats:', len(d['result']['content'][0]['text'].split()))"

test-health: build
	@echo "$(C_BLUE)Testing health check...$(C_RESET)"
	@echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"health","arguments":{}},"id":1}' | \
	  timeout 2 $(DIST_DIR)/$(BIN_NAME) 2>/dev/null | python3 -c "import json, sys; d=json.loads(sys.stdin.read()); print('pandoc' in d['result']['content'][0]['text'] and '✔ Health check passed' or '✖ Health check failed')"

# =============================================================================
# 🧹 CLEANUP
# =============================================================================
# help: 🧹 CLEANUP
# help: clean                 - Remove build & coverage artifacts
# help: clean-all             - Clean + remove tool binaries

.PHONY: clean clean-all

clean:
	@echo "$(C_BLUE)Cleaning build artifacts...$(C_RESET)"
	@rm -rf $(DIST_DIR) $(COVERPROFILE) $(COVERHTML)
	@echo "$(C_GREEN)✔ Workspace clean$(C_RESET)"

clean-all: clean
	@echo "$(C_BLUE)Removing tool binaries...$(C_RESET)"
	@rm -f $(GOBIN)/golangci-lint $(GOBIN)/staticcheck
	@echo "$(C_GREEN)✔ All clean$(C_RESET)"

# =============================================================================
# 🚀 QUICK DEVELOPMENT
# =============================================================================
# help: 🚀 QUICK DEVELOPMENT
# help: dev                   - Format, test, and build
# help: check                 - Run all checks (vet, lint, test)
# help: all                   - Full pipeline (fmt, check, build, test-pandoc)

.PHONY: dev check all

dev: fmt test build
	@echo "$(C_GREEN)✔ Development build complete$(C_RESET)"

check: vet lint test
	@echo "$(C_GREEN)✔ All checks passed$(C_RESET)"

all: fmt check build test-pandoc test-formats test-health
	@echo "$(C_GREEN)✔ Full pipeline complete$(C_RESET)"

# ---------------------------------------------------------------------------
# Default goal
# ---------------------------------------------------------------------------
.DEFAULT_GOAL := help
